home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
011
/
asm3.arc
/
PUSHDIR.ASM
< prev
next >
Wrap
Assembly Source File
|
1986-03-03
|
6KB
|
198 lines
main group code
code segment public para 'code'
assume cs:main
org 100h ;.COM file
BEGIN: jmp START ;program starts here
db "Copyright 1986 Ziff-Davis Publishing Co.",1Ah
signature db 'PUSHDIR VERSION 1.0'
lengthsignature = $ - signature
savedint16 dd ? ;old int 16h vector
nextpush dw offset main:push1dir ;next place to save a dir
push1dir db 67 dup (0) ;storage for a saved dir
push2dir db 67 dup (0) ;more storage
push3dir db 67 dup (0) ;more storage
push4dir db 67 dup (0) ;more storage
push5dir db 67 dup (0) ;more storage
push6dir db 67 dup (0) ;last storage
;up to here must be EXACTLY identical in both PUSHDIR and POPDIR so that
;popdir can know how to access the memory space reserved by the first
;pushdir.
;myint16 is an interrupt handler chained onto the existing interrupt handler.
;it is used to find out if PUSHDIR is already installed and if it is, where
;is it located? It works by adding another function to int 16h. To use it
;ax = 7788h, bx = 7789h, and ds:si points to the signature string. If any one
;of these conditions is not true, then the int 16h call is passed onto the
;old routine without doing anything. If they are all true, then we switch
;ax and bx and return ds = code segment (cs) of the interrupt handler.
myint16 proc far
pushf ;save flags
cmp ax,7788h ;possible signature request ?
je CHECKSIG ;yes
NOTSIG:
popf ;no - recover flags
jmp cs:[savedint16] ;go to old routine as normal
CHECKSIG:
cmp bx,7789h ;possible signature request ?
jne NOTSIG ;no
;ax and bx were correct for a signature request
;now see if ds:si was pointing to the signature string
;the whole idea of the signature is that is has to be
;totally unique so no other program could possibly use the same one.
push es ;save the registers we will use
push di
push cx
mov di,offset main:signature ;address of the signature
mov cx,lengthsignature ;length of the signature
repe cmpsb ;does string at ds:si match es:di ?
pop cx ;recover all registers we used
pop di
pop es
jne NOTSIG ;no, not correct signature
;yes, it was a signature request so return ds equal to the current code
;segment so subsequent pushdir's and popdir's know where the original
;is located.
push cs
pop ds ;set ds = cs
xchg ax,bx ;flip these two so we know that
;ds is being returned
popf ;recover original flags
iret ;return back to the program
;that called the int 16h
myint16 endp
endresident label byte ;label marking the end of the
;code to remain resident
;code after here will not remain resident
install db 1 ;0 = already installed, 1 = not installed
abortmsg db 'Error reading the current directory.$'
installmsg db 'PUSHDIR installed.$'
START:
sti ;turn interrupts on
;first check to see if PUSHDIR is already installed
mov ax,7788h ;signature request
mov bx,7789h ;signature request
mov si,offset main:signature ;point to signature
int 16h ;is it installed ?
assume ds:nothing
cmp bx,7788h ;were ax and bx switched ?
jne NOTINSTALLED ;no
cmp ax,7789h ;were ax and bx switched ?
jne NOTINSTALLED ;no
;yes it is installed already
mov cs:[install],0 ;don't install it again
NOTINSTALLED:
;ds = segment of the installation
;store the current directory, including disk drive letter
mov si,ds:[nextpush] ;get storage address for next push
add si,3 ;make room for d:\
mov dl,0 ;default drive
mov ah,47h ;dos function number
int 21h ;get current directory
jc ABORTERR ;error message if carry set
mov ah,19h ;dos function number
int 21h ;get the current drive
add al,'A' ;convert to ascii
mov byte ptr ds:[si-3],al ;add the "D:\" in front of path
mov byte ptr ds:[si-2],':'
mov byte ptr ds:[si-1],'\'
;now update [nextpush] for the next PUSHDIR
cmp ds:[nextpush],offset main:push6dir ;time to wrap around ?
je WRAPPUSH ;yes
add ds:[nextpush],67 ;no, point to next one
jmp short GOTNEXTPUSH
WRAPPUSH:
mov ds:[nextpush],offset main:push1dir ;wrap back to beginning
GOTNEXTPUSH:
cmp cs:[install],1 ;should we install it
je DOINSTALL ;yes
int 20h ;no, we are done
ABORTERR:
mov dx,offset main:abortmsg ;address of error message
mov ah,9 ;dos function number
int 21h ;show error message
int 20h ;end program on error
;if we got to here, then pushdir is not already installed,
;so we need to install it by making part of it memory resident.
DOINSTALL:
push cs
pop ds ;set ds = cs
assume ds:main
;save the current int 16h vector
push es ;save es
mov ax,3516h ;dos function 35h, vector 16h
int 21h ;get the existing vector into es:bx
mov word ptr [savedint16],bx ;save es:bx
mov word ptr [savedint16+2],es ;save es:bx
pop es ;recover es
;now set the new int 16h vector to point to my routine
mov dx,offset main:myint16 ;point to my new routine
mov ax,2516h ;dos function 25h, vector 16h
int 21h ;set new vector to ds:dx
;now show a message on the screen
;this message can be suppressed by redirecting output to NUL
;by using pushdir like this: PUSHDIR >NUL
mov dx,offset main:installmsg
mov ah,9
int 21h ;show installation message
;now free up the memory occupied by the envirnoment so it is not
;permanently wasted
mov ax,ds:[2ch] ;get segment of environment
mov es,ax ;load envirnoment segment into es
mov ah,49h ;dos function number
int 21h ;free the environment memory
;now terminate resident protecting only the first part of this program
mov dx,offset main:endresident ;point to end of resident code
add dx,0fh ;round up
mov cl,4
shr dx,cl ;convert to paragraphs (divide by 16)
mov ax,3100h ;dos function 31h, error code=0
int 21h ;terminate and remain resident
code ends
end begin ;start execution at BEGIN